package hapi.log;

import hapi.util.DynamicProxy;
import Type;

class DebugProxy<T> extends DynamicProxy<T> {
	
	public static function create<T>(inst:T):T {
		var before = new List();
		var after = new List();
		var clazz = Type.getClass(inst);
		var className = Type.getClassName(clazz);
		before.add(invokeddBefore(clazz, className));
		after.add(invokedAfter(clazz, className));
		return DynamicProxy.create(inst, clazz, before, after);
	}
	
	public static function invokeddBefore<T>(clazz:Class<T>, className) {
		var f = function(methodName:String, args:Array<Dynamic>):Void {
			haxe.Log.trace("("+readableArguments(args)+")", createPosInfos(className, methodName));
		}
		trace(f);
		return f;
	}
	
	public static function invokedAfter<T>(clazz:Class<T>, className) {
		var f = function(methodName:String, result:Dynamic):Void {
			haxe.Log.trace("\t->return " + readableValue(result),createPosInfos(className, methodName));
		}
		trace(f);
		return f;
	}
	
	private static function readableArguments(args:Array<Dynamic> ):String {
		if (args.length <= 0)
			return "";
		var buf = new StringBuf();
		var it = args.iterator();
		var a:Dynamic;
		while ( it.hasNext()) {
			a = it.next();
			buf.add(readableValue(a));
			if (it.hasNext()) buf.add(", ");
		}
		return buf.toString();
	}
	
	private static function readableValue(v:Dynamic):String {
		return Std.string(v) + "<" + readableType(v) + ">";
	}
	
	private static function readableType(v:Dynamic):String {
		var type = Type.typeof(v);
		return Std.string(type).substr(1);
	}
	
	private static function createPosInfos(className:String, methodName:String):haxe.PosInfos {
		return {
			fileName : "",
			lineNumber : 0,
			className : className,
			methodName : methodName,
			customParams : []
		}
	}
}